/*
 * @Author:
 * @Date: 2023-03-20 19:27:47
 * @LastEditors: xxx
 * @LastEditTime: 2023-07-13 15:13:07
 * @FilePath: \hart\hart\hart_frame.c
 * @Description:
 * email:
 * Copyright (c) 2023 by xxx, All Rights Reserved.
 */

#include "./inc/hart_frame.h"

static uint8_t *hart_frame_data_length_p;   // 帧数据长度位置
static uint8_t *hart_frame_response_code_p; // 帧响应码位置

/**
 * @brief 在处理请求开始时记录帧响应码起始位置
 * @param {uint8_t} *
 * @return {*}
 */
void hart_frame_response_code_start(uint8_t **data_p)
{
    hart_frame_response_code_p = *data_p;
}

/**
 * @brief 响应码第一个字节为通信有关的信息
 * @param {uint8_t} code
 * @return {*}
 * 1. 第7位如果是1，则剩余的位包含了有关通信错误的信息 response_error_communication_code_e
 * 2. 第7位如果是0，则剩余的位包含了有关通信正常的信息 response_communication_code_e
 */
void hart_frame_response_communication_code(uint8_t code)
{
    *hart_frame_response_code_p = code;
}

/**
 * @brief 响应码第二个字节为设备的操作状态有关的信息
 * 如在第一个字节中最高位置1，则该字节无意义
 * @param {uint8_t} code
 * @return {*}
 */
void hart_frame_slave_response_operate_code(hart_device_attribute_t *hart_device_attribute)
{
    /**
     * 判断当前设备状态的crc和device_status_crc是否一致
     * Note:
    Masters will issue this command whenever More Status Available (Bit 4 of the device status byte) issetAs a result, the Field Device must carefully define and contro the events and status information inthis command that affect these two device status bits. f the More Status Available bit is alwaysasserted. then communication bandwidth is effectively cut in half.
    */
    uint16_t crc = crc16_compute((uint8_t *)&hart_device_attribute->device_status.additional_device_status, sizeof(additional_device_status_t));
    if (hart_device_attribute->device_status.additional_device_status_crc != crc)
    {
        BIT_SET(hart_device_attribute->device_status.operational_state, DEVICE_OPERATIONAL_STATE_5);
    }

    *(hart_frame_response_code_p + 1) = hart_device_attribute->device_status.operational_state;
}

/**
 * @brief 响应码第二个字节为设备的操作状态有关的信息,主机默认回复0x00
 * @return {*}
 */
void hart_frame_master_response_operate_code(void)
{
    *(hart_frame_response_code_p + 1) = 0x00;
}

/**
 * @brief在处理请求开始时记录帧数据域长度起始位置
 * @param {uint8_t} *data_p
 * @return {*}
 */
void hart_frame_data_length_start(uint8_t **data_p)
{
    DBG_ASSERT(data_p != NULL __DBG_LINE);
    DBG_ASSERT(*data_p != NULL __DBG_LINE);

    hart_frame_data_length_p = *data_p;
}
/**
 * @brief在处理请求结束时记录帧数据长度位置
 * @param {uint8_t} *data_p
 * @return {*}
 */
void hart_frame_data_length_end(uint8_t *data_p)
{
    *hart_frame_data_length_p = data_p - hart_frame_data_length_p - 1; // 计算数据个数
    // LOG_PRINT("%d", *hart_frame_data_length_p);
}

// 判断指令是否是写
BOOL hart_is_write_command(uint16_t command)
{
    uint16_t cmd[] = {6, 17, 18, 19, 22, 38, 34, 35, 36, 37, 39, 40, 43, 44, 45, 46, 47, 49, 51, 52, 53, 55, 56, 58, 59, 64, 65, 66, 67, 68, 69, 79, 82, 83, 87, 88, 92, 97, 99, 100, 102, 103, 104, 107, 108, 109, 112, 116, 117, 118, 513, 517, 519, 521, 522, 524, 525, 526, 535, 539, 540};
    return is_in_array(cmd, sizeof(cmd) / sizeof(uint16_t), command);
}

// 判断版本是否支持当前指令
BOOL hart_is_support_command(uint16_t command)
{
    if (HART_PROTOCOL_VERSION_SUPPORT_COMMAND == 0)
    {
        return TRUE;
    }

    // 先判断是否在用户自定义的指令中
    uint16_t user_version[] = {130, 131, 132, 133, 140, 141, 254, 255, 256, 257, 258, 259, 260, 261, 500};
    if (is_in_array(user_version, sizeof(user_version) / sizeof(uint16_t), command))
    {
        return TRUE;
    }

    if (hart_get_current_protocol_version() == HART_PROTOCOL_VERSION_5)
    {
        uint16_t version[] = {0, 1, 2, 6, 11, 12, 13, 14, 15, 16, 17, 18, 19, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 107, 109, 110};
        return is_in_array(version, sizeof(version) / sizeof(uint16_t), command);
    }
    else if (hart_get_current_protocol_version() == HART_PROTOCOL_VERSION_7)
    {
        uint16_t version[] = {0, 1, 2, 3, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547};
        return is_in_array(version, sizeof(version) / sizeof(uint16_t), command);
    }
    else
    {
        return FALSE;
    }
}

// RTC时间转时间戳
uint32_t rtc_to_timestamp(void)
{
    uint32_t timestamp = 0;
    return timestamp;
}

void get_rtc_date(rtc_date_t *date)
{
#ifdef STM32

#else
    date->year = 23;
    date->month = 05;
    date->day = 10;
#endif
}

// 日期检测，年月日
BOOL check_date(rtc_date_t *date)
{
    if (date->year > 99)
    {
        return FALSE;
    }
    if (date->month < 1 || date->month > 12)
    {
        return FALSE;
    }
    if (date->day < 1 || date->day > 31)
    {
        return FALSE;
    }
    return TRUE;
}

// 判断是否是广播地址
BOOL is_broadcast_address(uint8_t *address, uint8_t len)
{
    for (uint8_t i = 0; i < len; i++)
    {
        if (*(address + i) != 0x00)
        {
            return FALSE;
        }
    }

    return TRUE;
}

// uint32转小时:分钟:秒:毫秒
void timestamp_to_hmsms(uint32_t timestamp, uint8_t *hmsms)
{
    uint32_t ms = timestamp % 1000;
    uint32_t s = timestamp / 1000;
    uint32_t m = s / 60;
    uint32_t h = m / 60;
    hmsms[0] = h;
    hmsms[1] = m % 60;
    hmsms[2] = s % 60;
    hmsms[3] = ms;
}

// assic转十六进制（assic-6）
void encode_ascii_6(const uint8_t *input, uint16_t input_length, uint8_t *output)
{
    uint8_t adjusted_input[input_length];
    uint16_t i = 0;

    osel_memset(adjusted_input, 0, input_length);

    for (i = 0; i < input_length; i++)
    {
        if (input[i] == 0x00)
        {
            adjusted_input[i] = 0x20;
            continue;
        }

        adjusted_input[i] = input[i] >= 0x40 ? input[i] - 0x40 : input[i];
    }

    uint16_t acs8_len = i + 1;
    uint16_t acs6_len = acs8_len * 6 / 8;
    for (i = 0; i < acs6_len; i++)
    {
        uint8_t pos = i * 8 / 6;
        uint8_t val = adjusted_input[pos] & 0x3f;
        uint8_t valNext = pos + 1 < acs8_len ? (adjusted_input[pos + 1] & 0x3f) : 0x20;
        uint8_t newVal = 0;
        switch (i % 3)
        {
        case 0:
            newVal = val << 2;
            newVal += valNext >> 4;
            break;
        case 1:
            newVal = val << 4;
            newVal += valNext >> 2;
            break;
        case 2:
            newVal = val << 6;
            newVal += valNext;
            break;
        }
        output[i] = newVal;
    }
}

// assic-6 转 assic的十六进制
void decode_ascii_6(const uint8_t *input, uint16_t input_length, uint8_t *output)
{
    uint16_t acs8_len = input_length * 8 / 6;

    for (uint16_t i = 0; i < acs8_len; i++)
    {
        uint8_t pos = i * 6 / 8;
        uint8_t val = input[pos];
        uint8_t valNext = pos + 1 < input_length ? input[pos + 1] : 0;
        uint8_t newVal = 0;
        switch (i % 4)
        {
        case 0:
            newVal = (val & 0xfc) >> 2;
            break;
        case 1:
            newVal = (val & 3) << 4;
            newVal += (valNext & 240) >> 4;
            break;
        case 2:
            newVal = (val & 15) << 2;
            newVal += (valNext & 192) >> 6;
            break;
        case 3:
            newVal = val & 0x3f;
            break;
        }
        if (newVal < 0x20)
            newVal += 64;
        if (newVal == 0x20)
            newVal = 0;
        output[i] = newVal;
    }
}

// Time由一个无符号的32位二进制整数组成，最低有效位表示1/32毫秒(即0.03125毫秒)。
void convert_time(uint32_t t, uint8_t *h, uint8_t *m, uint8_t *s)
{
    t = (t / 32);
    t = t / 1000;
    *h = t / 3600;
    *m = (t - (*h) * 3600) / 60;
    *s = t - (*h) * 3600 - (*m) * 60;
}

// Time由一个无符号的32位二进制整数组成，最低有效位表示1/32毫秒(即0.03125毫秒)。
void convert_timestrap(uint32_t *t, uint8_t h, uint8_t m, uint8_t s, uint16_t ms)
{
    *t = (h * 3600 + m * 60 + s) * 1000 + ms;
    *t = (*t) * 32;
}

// 年份转换，HART的年份是从1900年开始的，如果要转换到标准的年份，需要加上1900。另外，HART的年份是一个字节，所以最大只能表示到2155年。
void covert_year_rtc(uint8_t *year)
{
    uint8_t y = *year;
    *year = y -100;
}
